package com.macro.mall.common.log.aop;

import com.macro.mall.common.log.annotation.UnifiedLog;
import com.macro.mall.common.log.UnifiedLogUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 统一日志切面类
 * 通过AOP自动记录带有@UnifiedLog注解的方法执行日志
 * @author tiger
 */
@Aspect
@Component
public class UnifiedLogAspect {
    
    private static final Logger logger = LoggerFactory.getLogger(UnifiedLogAspect.class);
    
    @Around("@annotation(com.macro.mall.common.log.annotation.UnifiedLog)")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        
        // 获取方法信息
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        String className = method.getDeclaringClass().getName();
        String methodName = method.getName();
        
        // 获取注解信息
        UnifiedLog unifiedLogAnnotation = method.getAnnotation(UnifiedLog.class);
        String type = unifiedLogAnnotation.type();
        boolean logRequest = unifiedLogAnnotation.logRequest();
        boolean logResponse = unifiedLogAnnotation.logResponse();
        boolean logExecuteTime = unifiedLogAnnotation.logExecuteTime();
        
        Object[] args = joinPoint.getArgs();
        Object request = null;
        if (logRequest && args.length > 0) {
            request = args;
        }
        
        Object result = null;
        Throwable exception = null;
        
        try {
            // 执行方法
            result = joinPoint.proceed();
            return result;
        } catch (Throwable e) {
            exception = e;
            throw e;
        } finally {
            long executeTime = System.currentTimeMillis() - startTime;
            
            // 记录日志
            if (exception != null) {
                UnifiedLogUtil.log(type, className, methodName, request, null, 
                                 logExecuteTime ? executeTime : null, exception);
            } else {
                UnifiedLogUtil.log(type, className, methodName, request, 
                                 logResponse ? result : null, 
                                 logExecuteTime ? executeTime : null);
            }
        }
    }
}